//=====================================================================
//
// performance_test.cpp - KCP性能测试对比
//
// 编译命令：g++ performance_test.cpp ../ikcp.c -o performance_test -std=c++11
//
//=====================================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <vector>
#include <queue>
#include <chrono>

#include "../ikcp.h"

// 网络模拟器（带丢包和延迟）
class NetworkSimulator {
public:
    struct Packet {
        int peer;
        std::vector<char> data;
        unsigned int deliver_time;
    };
    
    std::queue<Packet> packets;
    unsigned int current_time;
    int loss_rate; // 丢包率（百分比）
    int min_delay, max_delay; // 延迟范围（毫秒）
    
    NetworkSimulator(int loss = 5, int min_rtt = 50, int max_rtt = 100) 
        : current_time(0), loss_rate(loss), min_delay(min_rtt/2), max_delay(max_rtt/2) {
        srand(time(nullptr));
    }
    
    void send(int peer, const char* data, int len) {
        // 模拟丢包
        if (rand() % 100 < loss_rate) {
            return; // 丢包
        }
        
        Packet pkt;
        pkt.peer = peer;
        pkt.data.assign(data, data + len);
        // 随机延迟
        int delay = min_delay + rand() % (max_delay - min_delay + 1);
        pkt.deliver_time = current_time + delay;
        packets.push(pkt);
    }
    
    bool recv(int peer, char* buffer, int& len) {
        if (packets.empty()) return false;
        
        Packet& pkt = packets.front();
        if (pkt.deliver_time > current_time || pkt.peer != peer) return false;
        
        len = pkt.data.size();
        memcpy(buffer, pkt.data.data(), len);
        packets.pop();
        return true;
    }
    
    void update(unsigned int time) {
        current_time = time;
    }
    
    void clear() {
        while (!packets.empty()) packets.pop();
    }
};

NetworkSimulator* g_network = nullptr;

// KCP输出回调函数
int udp_output(const char *buf, int len, ikcpcb *kcp, void *user) {
    int peer = *(int*)user;
    g_network->send(peer, buf, len);
    return 0;
}

// 获取当前时间（毫秒）
unsigned int get_time() {
    static auto start = std::chrono::high_resolution_clock::now();
    auto now = std::chrono::high_resolution_clock::now();
    return std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
}

// 性能测试函数
void performance_test(const char* mode_name, int nodelay, int interval, int resend, int nc) {
    printf("\n=== %s 模式测试 ===\n", mode_name);
    
    // 重置网络
    g_network->clear();
    
    // 创建KCP对象
    int peer1 = 0, peer2 = 1;
    ikcpcb *kcp1 = ikcp_create(0x11223344, &peer1);
    ikcpcb *kcp2 = ikcp_create(0x11223344, &peer2);
    
    // 设置输出回调
    ikcp_setoutput(kcp1, udp_output);
    ikcp_setoutput(kcp2, udp_output);
    
    // 配置窗口大小
    ikcp_wndsize(kcp1, 128, 128);
    ikcp_wndsize(kcp2, 128, 128);
    
    // 设置模式参数
    ikcp_nodelay(kcp1, nodelay, interval, resend, nc);
    ikcp_nodelay(kcp2, nodelay, interval, resend, nc);
    
    if (nodelay == 2) {
        kcp1->rx_minrto = 10;
        kcp1->fastresend = 1;
    }
    
    // 测试参数
    const int test_count = 100;
    const int packet_size = 64;
    char send_buffer[packet_size];
    char recv_buffer[1024];
    
    // 初始化发送数据
    for (int i = 0; i < packet_size; i++) {
        send_buffer[i] = i % 256;
    }
    
    unsigned int start_time = get_time();
    int sent_count = 0;
    int recv_count = 0;
    int total_rtt = 0;
    int max_rtt = 0;
    
    // 发送和接收循环
    for (int loop = 0; loop < 50000 && recv_count < test_count; loop++) {
        unsigned int current = start_time + loop; // 使用循环计数作为时间
        g_network->update(current);
        
        // 每20ms发送一个包
        if (sent_count < test_count && loop >= sent_count * 20) {
            // 在包头添加时间戳和序号
            *(unsigned int*)send_buffer = sent_count;
            *(unsigned int*)(send_buffer + 4) = current;
            
            ikcp_send(kcp1, send_buffer, packet_size);
            sent_count++;
        }
        
        // 更新KCP状态
        ikcp_update(kcp1, current);
        ikcp_update(kcp2, current);
        
        // 处理网络包
        int len;
        while (g_network->recv(1, recv_buffer, len)) {
            ikcp_input(kcp2, recv_buffer, len);
        }
        
        while (g_network->recv(0, recv_buffer, len)) {
            ikcp_input(kcp1, recv_buffer, len);
        }
        
        // 接收数据
        int recv_len = ikcp_recv(kcp2, recv_buffer, sizeof(recv_buffer));
        if (recv_len > 0) {
            unsigned int send_time = *(unsigned int*)(recv_buffer + 4);
            int rtt = current - send_time;
            total_rtt += rtt;
            if (rtt > max_rtt) max_rtt = rtt;
            recv_count++;
        }
        
        // 避免忙等待
        if (loop % 100 == 0) {
            usleep(1000); // 1ms
        }
    }
    
    unsigned int end_time = get_time();
    
    // 输出结果
    printf("发送包数: %d\n", sent_count);
    printf("接收包数: %d\n", recv_count);
    printf("总耗时: %u ms\n", end_time - start_time);
    if (recv_count > 0) {
        printf("平均RTT: %d ms\n", total_rtt / recv_count);
        printf("最大RTT: %d ms\n", max_rtt);
    }
    printf("丢包率: %.1f%%\n", (1.0 - (double)recv_count / sent_count) * 100);
    
    // 清理
    ikcp_release(kcp1);
    ikcp_release(kcp2);
}

int main() {
    printf("=== KCP 性能测试对比 ===\n");
    printf("网络环境: 5%% 丢包率, 50-100ms RTT\n");
    
    // 创建网络模拟器
    g_network = new NetworkSimulator(5, 50, 100);
    
    // 测试不同模式
    performance_test("默认", 0, 10, 0, 0);
    performance_test("普通", 0, 10, 0, 1);
    performance_test("快速", 2, 10, 2, 1);
    
    delete g_network;
    
    printf("\n=== 测试完成 ===\n");
    printf("说明:\n");
    printf("- 默认模式: 标准TCP类似行为\n");
    printf("- 普通模式: 关闭流控，提升性能\n");
    printf("- 快速模式: 启用所有优化，最低延迟\n");
    
    return 0;
}